﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Newtonsoft.Json;

namespace IncoolReg
{
    public static class SerializeHelper
    {
        /// <summary>
        /// 使用UTF8编码将byte数组转成字符串
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string ConvertToString(byte[] data)
        {
            return Encoding.UTF8.GetString(data, 0, data.Length);
        }

        /// <summary>
        /// 使用指定字符编码将byte数组转成字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string ConvertToString(byte[] data, Encoding encoding)
        {
            return encoding.GetString(data, 0, data.Length);
        }

        /// <summary>
        /// 使用UTF8编码将字符串转成byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] ConvertToByte(string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }

        /// <summary>
        /// 使用指定字符编码将字符串转成byte数组
        /// </summary>
        /// <param name="str"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static byte[] ConvertToByte(string str, Encoding encoding)
        {
            return encoding.GetBytes(str);
        }


        /// <summary>
        /// 将对象序列化为XML数据
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte[] SerializeToXml(object obj)
        {
            MemoryStream stream = new MemoryStream();
            XmlSerializer xs = new XmlSerializer(obj.GetType());
            xs.Serialize(stream, obj);

            byte[] data = stream.ToArray();
            stream.Close();

            return data;
        }


        /// <summary>
        /// 将XML数据反序列化为指定类型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T DeserializeWithXml<T>(byte[] data)
        {
            MemoryStream stream = new MemoryStream();
            stream.Write(data, 0, data.Length);
            stream.Position = 0;
            XmlSerializer xs = new XmlSerializer(typeof (T));
            object obj = xs.Deserialize(stream);

            stream.Close();

            return (T) obj;
        }

        /// <summary>
        /// 将XML数据反序列化为指定类型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T DeserializeWithXmlFile<T>(string xmlFilePath)
        {
            FileStream stream = File.Open(xmlFilePath, FileMode.OpenOrCreate);
            XmlSerializer xs = new XmlSerializer(typeof (T));
            object obj;
            if (stream.Length == 0)
            {
                obj = Activator.CreateInstance(typeof (T));
            }
            else
            {
                obj = xs.Deserialize(stream);
            }
            stream.Close();
            return (T) obj;
        }

        public static void SerializeToXmlFile(object obj, string xmlFilePath)
        {
            if (File.Exists(xmlFilePath))
            {
                File.Copy(xmlFilePath, xmlFilePath.Replace(".xml", ".bak"), true);
                File.Delete(xmlFilePath);
            }
            try
            {
                FileStream stream = File.Open(xmlFilePath, FileMode.Create);
                TextWriter tw = new StreamWriter(stream);
                //创建XML命名空间
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add("", "");
                XmlSerializer xs = new XmlSerializer(obj.GetType(), string.Empty);
                xs.Serialize(tw, obj, ns);
                tw.Close();
                stream.Close();
            }
            catch (Exception e)
            {
                string bakPath = xmlFilePath.Replace(".xml", ".bak");
                if (File.Exists(bakPath))
                {
                    File.Copy(bakPath, xmlFilePath, true);
                }
                throw e;
            }
        }

        /// <summary>
        /// 自jsonString序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonString"></param>
        /// <returns></returns>
        public static T DeserializeWithJson<T>(string jsonString)
        {
            T obj = JsonConvert.DeserializeObject<T>(jsonString);
            return obj;
        }

        public static T DeserializeWithJsonFile<T>(string path)
        {
            FileStream stream = File.OpenRead(path);
            StreamReader sr = new StreamReader(stream);
            string content = sr.ReadToEnd();
            sr.Close();
            stream.Close();
            return DeserializeWithJson<T>(content);
        }

        public static string SerializeToJson(object obj)
        {
            return JsonConvert.SerializeObject(obj);
        }

        public static void SerializeToJsonFile(object obj, string savePath)
        {
            if (File.Exists(savePath))
            {
                File.Copy(savePath, savePath+ ".bak", true);
                File.Delete(savePath);
            }
            try
            {
                string contentstr = JsonConvert.SerializeObject(obj);
                using (FileStream stream = File.Open(savePath, FileMode.Create))
                {
                    StreamWriter sw = new StreamWriter(stream);
                    sw.Write(contentstr);
                    sw.Flush();
                    sw.Close();
                    stream.Close();
                }
            }
            catch (Exception e)
            {
                string bakPath = savePath.Replace(".bak",string.Empty);
                if (File.Exists(bakPath))
                {
                    File.Copy(bakPath, savePath, true);
                }
                throw e;
            }
        }
    }
}